package com.qinglei.recoup.system.pojo;

import com.qinglei.recoup.hmp.pojo.vo.NegativeItemVO;
import com.qinglei.recoup.hmp.pojo.vo.SleepItemVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 健康报告评语
 *
 * @author 董强华
 * @Date 2021-07-15
 */
public class HealthStatusComment {

    private static final int sleepDurationMin = 7 * 60;  //睡眠时长下限 （分钟）
    private static final int sleepDurationMax = 10 * 60;  //睡眠时长上限 （分钟）
    private static final int outBedDurationMax = 5;  //离床时长上限 （分钟）
    private static final int outBedNumMax = 2;  //离床次数上限
    private static final int turnOverNumMax = 50;  //体动次数上限
    private static final int vitalityMin = 70;    //活力指数下限
    private static final int vitalityMax = 90;    //活力指数上限
    private static final int moraleMin = 70;      //情绪指数下限
    private static final int moraleMax = 90;      //情绪指数上限
    private static final int fallMax = 50;        //跌倒指数上限

    private static final int AHI1 = 5;
    private static final int AHI2 = 15;
    private static final int AHI3 = 25;
    private static final int AHI4 = 30;

    private static List<String> sleepDurationDefault = new ArrayList();


    static {

        sleepDurationDefault.add("昨晚睡得不错哟，今天可以和伙伴出去浪一浪");
        sleepDurationDefault.add("昨晚睡得不错哟，今天可以出门遛遛，感受一下大自然");
        sleepDurationDefault.add("昨晚睡得棒棒哒，约上伙伴出门high");
        sleepDurationDefault.add("昨晚睡得特别好，来个深呼吸，空气的味道都甜了吧");

    }

    /**
     * 8项指标&问题评语
     *
     * @return
     */
    public static String getCommentOne(HealthStatusCommentVO healthStatusCommentVO) {
        StringBuilder commentOneStringBuilder = new StringBuilder();

        Integer sleepDuration = healthStatusCommentVO.getSleepDuration();
        if (sleepDuration != null) {
            if (sleepDuration > sleepDurationMax) {
                commentOneStringBuilder.append("您的睡眠时长偏长，长期偏长的睡眠会容易疲劳，导致肥胖，可以尝试放松心情，提升睡眠质量，适度减少睡眠时间。");
            }
            if (sleepDuration < sleepDurationMin) {
                commentOneStringBuilder.append("您的睡眠时长偏短，长期偏短可能会对您的免疫力、认知能力等造成影响，可以尝试放松心情，增加睡眠时间。");
            }
        }
        Integer outBedDuration = healthStatusCommentVO.getOutBedDuration();
        if (outBedDuration != null) {
            if (outBedDuration > outBedDurationMax) {
                commentOneStringBuilder.append("您夜间离床时长偏长，您可以尝试调整饮食结构，保护肠胃健康。");
            }

        }

        Integer outBedNum = healthStatusCommentVO.getOutBedNum();
        if (outBedNum != null) {
            if (outBedNum > outBedNumMax) {
                commentOneStringBuilder.append("您夜间离床次数偏多，您可以关注饮食，尝试减少睡前食物摄入。");
            }

        }
        Integer turnOverNum = healthStatusCommentVO.getTurnOverNum();
        if (turnOverNum != null) {
            if (turnOverNum > turnOverNumMax) {
                commentOneStringBuilder.append("您的夜间体动次数偏多，您可以尝试在入睡前调整一个舒适的睡姿。");
            }
        }

        Integer vitality = healthStatusCommentVO.getVitality();
        if (vitality != null) {
            if (vitality < vitalityMin) {
                commentOneStringBuilder.append("不高兴，");
            }
        }
        Integer morale = healthStatusCommentVO.getMorale();
        if (morale != null) {
            if (morale < moraleMin) {
                commentOneStringBuilder.append("不快乐，");
            }
        }
        Integer fall = healthStatusCommentVO.getFall();
        if (fall != null) {
            if (fall > fallMax) {
                commentOneStringBuilder.append("危险，");
            }
        }
        if (StringUtils.isEmpty(commentOneStringBuilder)) {

        } else {
            commentOneStringBuilder.append("不用过于担忧哦，慢慢养成良好的睡眠习惯，您将拥有更健康的身体。");
        }

        return commentOneStringBuilder.toString();
    }

    public static String getCommentTwo(HealthStatusCommentVO oldHealthStatusCommentVO, HealthStatusCommentVO healthStatusCommentVO) {
        List<String> commentList = new ArrayList<>();
        Integer oldSleepDuration = oldHealthStatusCommentVO.getSleepDuration();
        Integer newSleepDuration = healthStatusCommentVO.getSleepDuration();

        if (oldSleepDuration != null && newSleepDuration != null) {
            if ((oldSleepDuration > sleepDurationMax || oldSleepDuration < sleepDurationMin) && (newSleepDuration >= sleepDurationMin && newSleepDuration <= sleepDurationMax)) {
                commentList.add("昨晚睡得真香，今天可以做一只精力旺盛的宝宝");
            }

            if ((oldSleepDuration >= sleepDurationMin && oldSleepDuration <= sleepDurationMax) && (newSleepDuration >= sleepDurationMin && newSleepDuration <= sleepDurationMax) && (newSleepDuration > oldSleepDuration)) {
                commentList.add("昨晚睡得比平时要长，今天一定是一个元气满满的一天");
            }

        }

        Integer oldOutBedDuration = oldHealthStatusCommentVO.getOutBedDuration();
        Integer newOutBedDuration = healthStatusCommentVO.getOutBedDuration();
        if (oldOutBedDuration != null && newOutBedDuration != null) {
            if (oldOutBedDuration > outBedDurationMax && newOutBedDuration <= outBedDurationMax) {
                commentList.add("昨晚睡得真踏实，今天一定是一个神清气爽的一天");
            }
            if (oldOutBedDuration <= outBedDurationMax && newOutBedDuration <= outBedDurationMax && newOutBedDuration < oldOutBedDuration) {
                commentList.add("昨晚睡得比平时安稳，有么有感受到自己体内的力量正在升腾");
            }

        }

        Integer oldOutBedNum = oldHealthStatusCommentVO.getOutBedNum();
        Integer newOutBedNum = healthStatusCommentVO.getOutBedNum();
        if (oldOutBedNum != null && newOutBedNum != null) {

            if (oldOutBedNum > outBedNumMax && newOutBedNum <= outBedNumMax) {
                commentList.add("昨晚睡得比平时安稳，有么有感受到自己体内的力量正在升腾");
            }
            if (oldOutBedNum <= outBedNumMax && newOutBedNum <= outBedNumMax && newOutBedNum < oldOutBedNum) {
                commentList.add("昨晚睡得比平时安稳，有么有感受到自己体内的力量正在升腾");
            }

        }

        Integer oldTurnOverNum = oldHealthStatusCommentVO.getTurnOverNum();
        Integer newTurnOverNum = healthStatusCommentVO.getTurnOverNum();
        if (oldTurnOverNum != null && newTurnOverNum != null) {
            if (oldTurnOverNum <= turnOverNumMax && newTurnOverNum <= turnOverNumMax && newTurnOverNum < oldTurnOverNum) {
                commentList.add("昨晚睡得比平时安稳，有么有感受到自己体内的力量正在升腾");
            }

            if (oldTurnOverNum > turnOverNumMax && newTurnOverNum <= turnOverNumMax) {
                commentList.add("昨晚睡得真踏实，今天一定是一个神清气爽的一天");
            }
        }

        Double oldAHI = oldHealthStatusCommentVO.getAHI();
        Double newAHI = oldHealthStatusCommentVO.getAHI();

        if (oldAHI != null && newAHI != null) {
            if (oldAHI < AHI1 && newAHI < AHI1 && newAHI < oldAHI) {
                commentList.add("昨晚呼吸质量有提升哟，今天的精力一定满满的");
            }

            if (newAHI <= AHI1) {
                commentList.add("昨晚呼吸通畅了不少，有么有感到自己正在上升的精气神");
            }
        }

        Random rand = new Random();

        if (commentList != null && commentList.size() > 0) {
            int random = rand.nextInt(commentList.size());
            return commentList.get(random);
        } else {
            int random = rand.nextInt(sleepDurationDefault.size());
            return sleepDurationDefault.get(random);
        }

    }

    public static String getCommentByAhi(Double ahi) {
        if (ahi < AHI1) {
            return "健康";
        } else if (ahi > AHI1 && ahi < AHI2) {
            return "低风险";
        } else if (ahi > AHI2 && ahi < AHI3) {
            return "中风险";
        } else {
            return "高风险";
        }
    }

    public static Map<String, Object> getCommentThree(HealthStatusCommentVO healthStatusCommentVO) {
        Map<String, Object> resultMap = new HashMap<>();
        Integer sleepDuration = healthStatusCommentVO.getSleepDuration();
        if (sleepDuration != null) {
            if (sleepDuration < sleepDurationMin) {
                resultMap.put("sleepDuration", "偏短");
            } else if (sleepDuration >= sleepDurationMin && sleepDuration <= sleepDurationMax) {
                resultMap.put("sleepDuration", "正常");
            } else {
                resultMap.put("sleepDuration", "偏长");
            }
        }

        Integer outBedDuration = healthStatusCommentVO.getOutBedDuration();
        if (outBedDuration != null) {
            if (outBedDuration <= outBedDurationMax) {
                resultMap.put("outBedDuration", "正常");
            } else {
                resultMap.put("outBedDuration", "偏长");
            }
        }

        if (healthStatusCommentVO.getOutBedNum() != null) {
            if (healthStatusCommentVO.getOutBedNum() <= outBedNumMax) {
                resultMap.put("outBedNum", "正常");
            } else {
                resultMap.put("outBedNum", "偏多");
            }
        }

        if (healthStatusCommentVO.getTurnOverNum() != null) {
            if (healthStatusCommentVO.getTurnOverNum() <= turnOverNumMax) {
                resultMap.put("turnOverNum", "正常");
            } else {
                resultMap.put("turnOverNum", "偏多");
            }
        }

        if (healthStatusCommentVO.getMorale() != null) {

            if (healthStatusCommentVO.getMorale() < moraleMin) {
                resultMap.put("morale", "偏低");
            } else if (healthStatusCommentVO.getMorale() >= moraleMin && healthStatusCommentVO.getMorale() <= moraleMax) {
                resultMap.put("morale", "正常");
            } else {
                resultMap.put("morale", "优秀");
            }
        }

        if (healthStatusCommentVO.getVitality() != null) {

            if (healthStatusCommentVO.getVitality() < vitalityMin) {
                resultMap.put("vitality", "偏低");
            } else if (healthStatusCommentVO.getVitality() >= vitalityMin && healthStatusCommentVO.getVitality() <= vitalityMax) {
                resultMap.put("vitality", "正常");
            } else {
                resultMap.put("vitality", "优秀");
            }
        }


        if (healthStatusCommentVO.getFall() != null) {
            if (healthStatusCommentVO.getFall() <= fallMax) {
                resultMap.put("fall", "正常");
            } else {
                resultMap.put("fall", "偏高");
            }
        }

        return resultMap;
    }

    /**
     * 获取负面报告列表
     *
     * @param healthStatusCommentVO
     * @return
     */
    public static List<NegativeItemVO> getNegativeCommentList(HealthStatusCommentVO healthStatusCommentVO) {
        List<NegativeItemVO> negativeList = new ArrayList<>();
        Integer sleepDuration = healthStatusCommentVO.getSleepDuration();
        if (sleepDuration != null) {
            if (sleepDuration > sleepDurationMax) {
                NegativeItemVO negativeItemVO = new NegativeItemVO();
                negativeItemVO.setName("睡眠时长");
                negativeItemVO.setComment("偏长");
                negativeItemVO.setRemark("您的睡眠时长偏长，长期偏长的睡眠会容易疲劳，导致肥胖，可以尝试放松心情，提升睡眠质量，适度减少睡眠时间。");
                negativeList.add(negativeItemVO);
            }
            if (sleepDuration < sleepDurationMin) {
                NegativeItemVO negativeItemVO = new NegativeItemVO();
                negativeItemVO.setName("睡眠时长");
                negativeItemVO.setComment("偏短");
                negativeItemVO.setRemark("您的睡眠时长偏短，长期偏短可能会对您的免疫力、认知能力等造成影响，可以尝试放松心情，增加睡眠时间。");
                negativeList.add(negativeItemVO);
            }
        }
        Integer outBedDuration = healthStatusCommentVO.getOutBedDuration();
        if (outBedDuration != null) {
            if (outBedDuration > outBedDurationMax) {
                NegativeItemVO negativeItemVO = new NegativeItemVO();
                negativeItemVO.setName("离床时长");
                negativeItemVO.setComment("偏长");
                negativeItemVO.setRemark("您夜间离床时长偏长，您可以尝试调整饮食结构，保护肠胃健康。");
                negativeList.add(negativeItemVO);
            }
        }

        Integer outBedNum = healthStatusCommentVO.getOutBedNum();
        if (outBedNum != null) {
            if (outBedNum > outBedNumMax) {
                NegativeItemVO negativeItemVO = new NegativeItemVO();
                negativeItemVO.setName("离床次数");
                negativeItemVO.setComment("偏多");
                negativeItemVO.setRemark("您夜间离床次数偏多，您可以关注饮食，尝试减少睡前食物摄入。");
                negativeList.add(negativeItemVO);
            }

        }
        Integer turnOverNum = healthStatusCommentVO.getTurnOverNum();
        if (turnOverNum != null) {
            if (turnOverNum > turnOverNumMax) {
                NegativeItemVO negativeItemVO = new NegativeItemVO();
                negativeItemVO.setName("体动次数");
                negativeItemVO.setComment("偏多");
                negativeItemVO.setRemark("您的夜间体动次数偏多，您可以尝试在入睡前调整一个舒适的睡姿。");
                negativeList.add(negativeItemVO);
            }
        }
        return negativeList;
    }

    /**
     * 获取睡眠详情列表
     *
     * @param sleepInfoCommentDTO
     * @return
     */
    public static List<SleepItemVO> getSleepInfoList(SleepInfoCommentDTO sleepInfoCommentDTO) {
        List<SleepItemVO> sleepItemList = new ArrayList<>();
        // 睡眠时长
        SleepItemVO sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("睡眠时长");
        sleepItemVO.setValue(getDurationText(sleepInfoCommentDTO.getSleepDuration()));
        if (sleepInfoCommentDTO.getSleepDuration() < 7 * 60) {
            sleepItemVO.setComment("偏短");
        } else if (sleepInfoCommentDTO.getSleepDuration() > 10 * 60) {
            sleepItemVO.setComment("偏长");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        //睡眠
        List<Integer> sleepItem = new ArrayList<>();
        sleepItem.add(sleepInfoCommentDTO.getDeepSleepDuration());  //深睡
        sleepItem.add(sleepInfoCommentDTO.getLightSleepDuration()); //浅睡
        sleepItem.add(sleepInfoCommentDTO.getClearSleepDuration()); //清醒时长
        sleepItem.add(sleepInfoCommentDTO.getOutBedDuration());// 离床时长

        // 深睡时长
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("深睡时长");
        sleepItemVO.setValue(getDurationText(sleepInfoCommentDTO.getDeepSleepDuration()));
//        sleepItemVO.setRatio(getPercentageMini1(sleepInfoCommentDTO.getDeepSleepDuration(), sleepInfoCommentDTO.getSleepDuration()));
        sleepItemVO.setRatio(getPercentIntergerValue(sleepItem, sleepInfoCommentDTO.getSleepDuration(),0));
        if (sleepItemVO.getRatio() < 20) {
            sleepItemVO.setComment("偏少");
        } else if (sleepItemVO.getRatio() > 60) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 浅睡时长
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("浅睡时长");
        sleepItemVO.setValue(getDurationText(sleepInfoCommentDTO.getLightSleepDuration()));
        sleepItemVO.setRatio(getPercentIntergerValue(sleepItem, sleepInfoCommentDTO.getSleepDuration(),1));
        if (sleepItemVO.getRatio() < 20) {
            sleepItemVO.setComment("偏少");
        } else if (sleepItemVO.getRatio() > 60) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 清醒时长
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("清醒时长");
        sleepItemVO.setValue(getDurationText(sleepInfoCommentDTO.getClearSleepDuration()));
        sleepItemVO.setRatio(getPercentIntergerValue(sleepItem, sleepInfoCommentDTO.getSleepDuration(),2));
        if (sleepItemVO.getRatio() > 5) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 离床时长
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("离床时长");
        sleepItemVO.setValue(getDurationText(sleepInfoCommentDTO.getOutBedDuration()));
        sleepItemVO.setRatio(getPercentIntergerValue(sleepItem, sleepInfoCommentDTO.getSleepDuration(),3));
        if (sleepItemVO.getRatio() > 5) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 离床次数
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("离床次数");
        sleepItemVO.setValue(sleepInfoCommentDTO.getOutBedNum() + "次");
        if (sleepInfoCommentDTO.getOutBedNum() > 2) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 体动次数
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("体动次数");
        sleepItemVO.setValue(sleepInfoCommentDTO.getTurnOverNum() + "次");
        if (sleepInfoCommentDTO.getTurnOverNum() > 50) {
            sleepItemVO.setComment("偏多");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 睡眠效率
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("睡眠效率");
        int sleepTime = sleepInfoCommentDTO.getDeepSleepDuration() + sleepInfoCommentDTO.getLightSleepDuration();
        int inBedTime = sleepInfoCommentDTO.getDeepSleepDuration() + sleepInfoCommentDTO.getLightSleepDuration() + sleepInfoCommentDTO.getClearSleepDuration();
        Integer percentage = getPercentage(sleepTime, inBedTime);
        sleepItemVO.setValue(percentage + "%");
        if (percentage < 80) {
            sleepItemVO.setComment("偏低");
        } else {
            sleepItemVO.setComment("正常");
        }
        sleepItemList.add(sleepItemVO);

        // 睡眠呼吸
        sleepItemVO = new SleepItemVO();
        sleepItemVO.setName("睡眠呼吸");
        if (sleepInfoCommentDTO.getAhi() < 5) {
            sleepItemVO.setComment("健康");
        } else {
            sleepItemVO.setComment("需关注");
        }
        sleepItemList.add(sleepItemVO);
        return sleepItemList;
    }

    /**
     * 转换时长文本
     *
     * @param duration
     * @return
     */
    private static String getDurationText(Integer duration) {
        Integer hour = duration / 60;
        Integer minute = duration % 60;
        StringBuilder sb = new StringBuilder();
        if (hour > 0) {
            sb.append(hour);
            sb.append("小时");
        }
        sb.append(minute);
        sb.append("分钟");
        return sb.toString();
    }

    /**
     * 转换百分数
     * @param part
     * @param whole
     * @return
     */
    private static Integer getPercentage(Integer part, Integer whole) {
        return Math.round(((float) part) / whole * 100);
    }

    /**
     * 转换百分数
     * @param part ge
     * @param whole zong
     * @return
     */
    private static Integer getPercentageMini1(Integer part, Integer whole) {
        int round = Math.round(((float) part) / whole * 100);
        if(round == 0 && part >0)
            round =1;
        return round;
    }


    /**
     * 数组
     * @param arr 数组
     * @param sum 总数
     * @param idx 索引
     * @return
     */
    public static Integer getPercentIntergerValue(List<Integer> arr,double sum,int idx){
        if(CollectionUtils.isEmpty(arr))
            return 0;
        int[] ints = arr.stream().mapToInt(Integer::valueOf).toArray();
        double percentValue = getPercentValue(ints, sum, idx, 0);
        int intValue = (int) percentValue;
        return intValue;
    }



    /**
     * 数组
     * @param arr 数组
     * @param sum 总数
     * @param idx 索引
     * @param precision 精度
     * @return
     */
    public static double getPercentValue(int[] arr,double sum,int idx,int precision){
        if ((arr.length - 1) < idx) {
            return 0;
        }
        //求和
        if (sum <= 0) {
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
        }
        //10的2次幂是100，用于计算精度。
        double digits = Math.pow(10, precision);
        //扩大比例100
        double[] votesPerQuota = new double[arr.length];
        for (int i = 0; i < arr.length; i++) {
            double val = arr[i] / sum * digits * 100;
            votesPerQuota[i] = val;
        }
        //总数,扩大比例意味的总数要扩大
        double targetSeats = digits * 100;
        //再向下取值，组成数组
        double[] seats = new double[arr.length];
        for (int i = 0; i < votesPerQuota.length; i++) {
            seats[i] = Math.floor(votesPerQuota[i]);
            if(seats[i] == 0 && votesPerQuota[i] >0 && votesPerQuota[i]<1){
                seats[i] = 1;
            }
        }
        //再新计算合计，用于判断与总数量是否相同,相同则占比会100%
        double currentSum = 0;
        for (int i = 0; i < seats.length; i++) {
            currentSum += seats[i];
        }
        //余数部分的数组:原先数组减去向下取值的数组,得到余数部分的数组
        double[] remainder = new double[arr.length];
        for (int i = 0; i < seats.length; i++) {
            remainder[i] = votesPerQuota[i] - seats[i];
        }
        while (currentSum < targetSeats) {
            double max = 0;
            int maxId = 0;
            int len = 0;
            for (int i = 0; i < remainder.length; ++i) {
                if (remainder[i] > max) {
                    max = remainder[i];
                    maxId = i;
                }
            }
            //对最大项余额加1
            ++seats[maxId];
            //已经增加最大余数加1,则下次判断就可以不需要再判断这个余额数。
            remainder[maxId] = 0;
            //总的也要加1,为了判断是否总数是否相同,跳出循环。
            ++currentSum;
        }
        while (currentSum > targetSeats) {
            double max = 0;
            int maxId = 0;
            for (int i = 0; i < remainder.length; ++i) {
                if (remainder[i] > max) {
                    max = remainder[i];
                    maxId = i;
                }
            }
            //对最大项余额加1
            --seats[maxId];
            --currentSum;
        }
        // 这时候的seats就会总数占比会100%
        return seats[idx] / digits;
    }

    public static void main(String[] args) {
        System.err.println(sleepDurationDefault);
    }


}
